#ifndef __MEMSLOT_H
#define __MEMSLOT_H
#include "stdtype.h"
#include "mmblock.h"
#include "mmflat.h"
#include "mutex.h"

/* the default maxmium slot count */
#define MX_MEMSLOT_MAX ((mx_uint8_t)MXSETUP_MEMSLOT_MAX)

/* invalid id definition */
#define MX_MEMSLOT_ID_INVAL MX_MEMSLOT_MAX
/* check the validity of the `id` */
#define MX_MEMSLOT_ID_CHECK(id) ((mx_uint8_t)(id) < MX_MEMSLOT_MAX)

/* definition the memory slot type */
#define MX_MEMSLOT_TYPE_BLOCK 0     // for mmblock
#define MX_MEMSLOT_TYPE_FLAT 1      // for mmflat
#define MX_MEMSLOT_TYPE_MAX 2
#define MX_MEMSLOT_TYPE_INVAL MX_MEMSLOT_TYPE_MAX

/**
 * definition the memory slot perf
 * @note: the smaller the value, the higher the performance
 */
#define MX_MEMSLOT_PERF_CACHE 0     // internal cache of cpu
#define MX_MEMSLOT_PERF_REG 1       // internal register of cpu
#define MX_MEMSLOT_PERF_ISRAM 2     // internal sram of cpu
#define MX_MEMSLOT_PERF_IDRAM 3     // internal dram of cpu
#define MX_MEMSLOT_PERF_SRAM 4      // external sram
#define MX_MEMSLOT_PERF_DRAM 5      // external dram
#define MX_MEMSLOT_PERF_PSRAM 6     // external psram
#define MX_MEMSLOT_PERF_MAX 7
#define MX_MEMSLOT_PERF_INVAL MX_MEMSLOT_PERF_MAX

/* affinity attributes */
#define __MX_MEMSLOT_AFFI_ATTRS \
            mx_uint8_t id;      /* the index of memory slot array */    \
            mx_uint8_t align;   /* the alignment during memory allocation (the exponent of 2) */    \
            mx_uint8_t type;    /* the type of memory slot */   \
            mx_uint8_t perf;    /* the performance of memory hardware */

/* the attributes of `mx_memslot_t` structure */
#define __MX_MEMSLOT_ATTRS  \
            __MX_MEMSLOT_AFFI_ATTRS;    \
            mx_mutex_t mutex;   /* for memory allocate/free operations */

/* the attributes of `mx_memslot_param_t` structure */
#define __MX_MEMSLOT_PARAM_ATTRS  \
            __MX_MEMSLOT_AFFI_ATTRS \
            mx_void_pt start;   /* the start address of memory space */   \
            mx_usize_t size;    /* the size of memory space */

/**
 * this function will iterate the slot list in system
 * @prototype: void mx_memslot_foreach (<elm>, {...});
 */
#define mx_memslot_foreach(elm, ...) {  \
    for (mx_usize_t __i = 0; __i < MX_MEMSLOT_MAX; __i++) { \
        mx_memslot_pt elm = __mx_memslot_slots[__i];    \
        if (elm != mx_null) {   \
            __VA_ARGS__ \
        }   \
    }   \
}

/**
 * the memory area structure definitioin
 */
typedef struct
{
    mx_void_pt start;
    mx_usize_t size;
} mx_memory_area_t, *mx_memory_area_pt;

/**
 * definition memory slot descriptor
 */
typedef struct
{
    __MX_MEMSLOT_ATTRS;
} mx_memslot_t, *mx_memslot_pt;

/**
 * definition the parameter descriptor of memory slot
 */
typedef struct
{
    __MX_MEMSLOT_PARAM_ATTRS;
} mx_memslot_param_t, *mx_memslot_param_pt;

typedef struct
{
    __MX_MEMSLOT_PARAM_ATTRS;
    mx_usize_t max;     // maximum allocatable memory
    mx_usize_t min;     // minimum allocatable memory
} mx_memslot_info_t, *mx_memslot_info_pt;

/// ------------------------------------------------------------------------ block slot

typedef struct
{
    __MX_MEMSLOT_ATTRS;
    mx_mmblock_t mmblock;
} mx_memslot_block_t, *mx_memslot_block_pt;

typedef struct
{
    __MX_MEMSLOT_PARAM_ATTRS;
    mx_usize_t bsize;       // block size
} mx_memslot_block_param_t, *mx_memslot_block_param_pt;

/// ------------------------------------------------------------------------ flat slot

typedef struct
{
    __MX_MEMSLOT_ATTRS;
    mx_mmflat_t mmflat;
} mx_memslot_flat_t, *mx_memslot_flat_pt;

/// ------------------------------------------------------------------------ common functions

/* for `mx_memslot_foreach` */
extern mx_memslot_pt __mx_memslot_slots[MX_MEMSLOT_MAX];

/* get slot's attributes (descriptor) by id */
mx_memslot_pt mx_memslot_get (mx_uint8_t id);
/* mount the specified memory slot to system */
void mx_memslot_mount (mx_memslot_pt pslot, mx_memslot_param_pt param);
/* allocate memory from specified memory slot */
mx_memory_area_t mx_memslot_alloc (mx_memslot_pt pslot, mx_usize_t size);
/* free memory to specified memory slot */
void mx_memslot_free (mx_memslot_pt pslot, mx_void_pt addr);
/* get the information of memory slot */
void mx_memslot_getinfo (mx_memslot_pt pslot, mx_memslot_info_pt info);

#endif
